-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trace static level filtering #987
Trace static level filtering #987
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution! This seems like a good start; I left some pointers in comments.
For next steps, we'll need to add if
statements to the event!
and span!
macros comparing the event/span's verbosity level with the static max. I gave an example of what this would look like in the description of issue #959.
tokio-trace/src/lib.rs
Outdated
/// An enum representing the available verbosity level filters of the logger. | ||
#[repr(usize)] | ||
#[derive(Copy, Clone, Debug, Hash)] | ||
pub enum LevelFilter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For forwards-compatibility reasons, we try to avoid having enum types in public APIs. Can this be a struct wrapping an inner private enum type instead? Refer to how the Level
type in tokio-trace-core
is implemented:
tokio/tokio-trace/tokio-trace-core/src/metadata.rs
Lines 224 to 272 in 92d5120
// ===== impl Level ===== | |
impl Level { | |
/// The "error" level. | |
/// | |
/// Designates very serious errors. | |
pub const ERROR: Level = Level(LevelInner::Error); | |
/// The "warn" level. | |
/// | |
/// Designates hazardous situations. | |
pub const WARN: Level = Level(LevelInner::Warn); | |
/// The "info" level. | |
/// | |
/// Designates useful information. | |
pub const INFO: Level = Level(LevelInner::Info); | |
/// The "debug" level. | |
/// | |
/// Designates lower priority information. | |
pub const DEBUG: Level = Level(LevelInner::Debug); | |
/// The "trace" level. | |
/// | |
/// Designates very low priority, often extremely verbose, information. | |
pub const TRACE: Level = Level(LevelInner::Trace); | |
} | |
#[repr(usize)] | |
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] | |
enum LevelInner { | |
/// The "error" level. | |
/// | |
/// Designates very serious errors. | |
Error = 1, | |
/// The "warn" level. | |
/// | |
/// Designates hazardous situations. | |
Warn, | |
/// The "info" level. | |
/// | |
/// Designates useful information. | |
Info, | |
/// The "debug" level. | |
/// | |
/// Designates lower priority information. | |
Debug, | |
/// The "trace" level. | |
/// | |
/// Designates very low priority, often extremely verbose, information. | |
Trace, | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hawkw Thanks for this, if we already have this Level
, perhaps we can just use Level
for this purpose?
Only Off
level is missing, do we actually need it? what do you think?
It seems to be private struct though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hawkw Thanks for this, if we already have this
Level
, perhaps we can just useLevel
for this purpose?Only
Off
level is missing, do we actually need it? what do you think?
I think we will want an OFF
level for the static filter, so that tokio-trace
can be completely disabled in release mode, etc. So, we'll probably need a separate LevelFilter
type.
The implementation can be the same as tokio-trace-core
s Level
type, but with the addition of an OFF
level. We will want to implement the PartialOrd
trait for comparing LevelFilter
s with Level
s, (impl PartialOrd<Level> for LevelFilter
, with the same ordering as for Level
s, but with LevelFilter::OFF
considered less than all Level
s
It seems to be private struct though.
The Level
struct is public:
pub struct Level(LevelInner); |
while the
LevelInner
enum is private:enum LevelInner { |
We'll want our LevelFilter
type to follow the same pattern.
@hawkw Hey mate, thanks again I have updated the code to the best I can understand. Please give some thoughts about the implementation. If it is ok (or almost there) I can start looking into tests for this feature. 😄 |
And remove cfg-if dependency
Hey @hawkw I have updated the implementation, can you check again? cheers, A bit strange is that I have to |
It looks like the CI build failure is due to an error installing Rust, so that's not your fault. I'm going to restart the build. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're on the right track, but there are a couple more changes I'd like made.
In particular:
- can we rename the fully disabled
LevelFilter
from "zero" to "off" (which is whatlog
calls it)? This would mean renaming the associated const as well as the feature flags. - I just noticed an issue with the way the
cfg
attributes are being used that I think means we'll probably want to bring back thecfg_if
macro, despite what I said earlier. Sorry about that.
That said, I really like the way you've implemented this feature, and I think we're most of the way there. Thanks for putting up with all the changes I keep requesting!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good. I commented on a couple more nits. I think if we address them and my comment about changing the feature flags (#987 (comment)), this will be good to merge (although tests would still be nice...)
tokio-trace/src/level_filters.rs
Outdated
use std::cmp::Ordering; | ||
use tokio_trace_core::Level; | ||
|
||
/// Describes the level of verbosity of a span or event. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment copied from Level
? I think it should probably describe the difference between a Level
and a LevelFilter
...
Hey @hawkw thanks so much for your guidance so far. Even though I would like to add the test, and a vaguely understand the test in Thanks again! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some comments describing how we can adapt the log
crate's tests to work for tokio-trace
. Let me know if you get stuck!
Hey @hawkw I have updated to the best I can understand, but it is probably missing something. Let me know if you want to add or remove anything. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@phungleson The test looks good to me --- now all we have to do is integrate it into the rest of the test suite.
In addition to the inline comments I left, I think we'd want to add it to the list here:
Lines 39 to 49 in 678f15b
crates: | |
- tokio-buf | |
- tokio-codec | |
- tokio-current-thread | |
- tokio-executor | |
- tokio-io | |
- tokio-sync | |
- tokio-threadpool | |
- tokio-timer | |
- tokio-trace | |
- tokio-trace/tokio-trace-core |
so that the test actually gets run on CI.
Once we do that, I think this is good to merge! Thanks for working on this!
fn exit(&self, _span: &Id) {} | ||
} | ||
|
||
fn main() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change this from a main method to a test? so
#[test]
fn test_static_max_level_features() {
// ...
}
I think in order for cargo test
to pick this up, we'd also want to move the file into atokio-trace/test_static_max_level_features/tests/
directory.
version = "0.1.0" | ||
publish = false | ||
|
||
[[bin]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the test was moved into tests
, the whole [[bin]]
section needs to be removed.
Doing so will fix the CI build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beyond one issue in azure-pipelines.yml
that should be trivial to fix, this looks good to me. Thanks @phungleson!
I noticed that the FreeBSD CI build is failing, but I don't think that's your fault --- we've been having trouble with it recently. I can sort that out before merging this PR.
Thanks so much for all the guidance @hawkw I have made the changes and things seem ok, except failing FreeBSD! |
Okay, I've figured out what's up with the CI build on FreeBSD: the FreeBSD build runs tests using What this means is that on FreeBSD, one version of An obvious solution is to just change the Cirrus CI config to do the same thing as the Azure Pipelines CI builds, but I'd prefer to have |
@phungleson if I can get you to merge https://github.com/phungleson/tokio/pull/1 into your fork, I think that will resolve the FreeBSD CI issues and we'll be able to move forward with this! |
Fix FreeBSD CI
Looks pretty good, thanks @hawkw I have learned a lot through the process! |
@phungleson Great, thanks for your contribution! I'm going to go ahead and merge this when the CI build passes. |
aaaand....merged! thanks again @phungleson! |
Cool awesome! thanks again for all your help @hawkw Do you know any particular issues that can be suitable to look into? (and hope I can be more helpful this time 😄) |
@phungleson you'll probably want to keep your eye out for issues tagged as "easy". There is also a "good first issue" tag in the |
## Motivation `tokio-trace` should have static verbosity level filtering, like the `log` crate. The static max verbosity level should be controlled at compile time with a set of features. It should be possible to set a separate max level for release and debug mode builds. ## Solution We can do this fairly similarly to how the `log` crate does it: `tokio-trace` should export a constant whose value is set based on the static max level feature flags. Then, we add an if statement to the `span!` and `event!` macros which tests if that event or span's level is enabled. Closes #959
Motivation
tokio-trace
should have static verbosity level filtering, like thelog
crate. The static max verbosity level should be controlled at compile time with a set of features. It should be possible to set a separate max level for release and debug mode builds.#959
Solution
We can do this fairly similarly to how the
log
crate does it:tokio-trace
should export a constant whose value is set based on the static max level feature flags. Then, we can add an if statement to thespan!
andevent!
macros, like